#include <ctype.h>

#include "TextReader.h"


CTextReader::CTextReader(const int OnlySpaces, const int SkipComments)
	{
	line = 1;
	col = 1;
	spaces = OnlySpaces;
	skipcomments = SkipComments;
	cur = EOF;
	}


CTextReader::~CTextReader()
	{
	cur = EOF;
	}


int CTextReader::CurC()
	{
	if (skipcomments && cur == ';')
		return (spaces ? ' ' : '\n');
	else if (spaces && isspace(cur))
		return (' ');
	else
		return (cur);
	}


int CTextReader::NextC()
	{
	int c;

	switch (cur)
		{
		case EOF :
			return EOF;
		case ';' :
			if (!skipcomments)
				{
				col++;
				break;
				}
			do
				c = getch();
				while (c != EOF && c != '\n');
			if (c == EOF)
				return (cur = EOF); /* Zuweisung! */
			/* weiter mit \n */
		case '\n' :
			line++;
			col = 1;
			break;
		case '\t' :
			col = ((col + 7) / 8) * 8 + 1;
			break;
		default :
			col++;
			break;
		}
	cur = getch();
	return (CurC());
	} /* TextNextC() */


int CTextReader::NextNonSpace()
	{
	while (isspace(CurC()))
		NextC();
	return (CurC());
	}


int CTextReader::GetC()
	{
	int c;

	c = CurC();
	NextC();
	return (c);
	}


int CTextReader::GetNonSpace()
	{
	NextNonSpace();
	return (GetC());
	}


int CTextReader::GetName(char *s, int max)
	{
	char *p;
	int c;

	NextNonSpace();
	p = s;
	c = CurC();
	while (isalnum(c))
		{
		if (p - s < max-1)
			*p++ = c;
		NextC();
		c = CurC();
		}
	*p = '\0';
	return ((c == EOF && p == s) ? EOF : p - s);
	}


int CTextReader::GetString(CString &s, char *Delim)
	{
	int c;

	NextNonSpace();
	s.Empty();
	if (Delim == NULL)
		Delim = "";
	c = CurC();
	while (c != EOF
		   && c != '\n'
		   && !(spaces && c == ' ')
		   && strchr(Delim, c) == NULL)
		{
		s += c;
		NextC();
		c = CurC();
		}
	return ((c == EOF && s.IsEmpty()) ? EOF : s.GetLength());
	}



int CTextReader::GetString(char *s, int max, char *Delim)
	{
	char *p;
	int c;

	NextNonSpace();
	p = s;
	if (Delim == NULL)
		Delim = "";
	c = CurC();
	while (c != EOF
		   && c != '\n'
		   && !(spaces && c == ' ')
		   && strchr(Delim, c) == NULL)
		{
		if (p - s < max-1)
			*p++ = c;
		NextC();
		c = CurC();
		}
	*p = '\0';
	return ((c == EOF && p == s) ? EOF : p - s);
	}


int CTextReader::GetInt(int &i)
	{
	int neg;

	NextNonSpace();
	i = 0;
	neg = 0;
	switch (CurC())
		{
		case EOF :
			return (EOF);
		case '+' :
			NextC();
			break;
		case '-' :
			neg = 1;
			NextC();
			break;
		}
	if (!isdigit(CurC()))
		return (0);
	while (isdigit(CurC()))
		{
		i = i * 10 + CurC() - '0';
		NextC();
		}
	if (neg)
		i = -i;
	return (1);
	}


CTextArchReader::CTextArchReader(CArchive &Arch, const int OnlySpaces,
			                     const int SkipComments)
	: CTextReader(OnlySpaces, SkipComments)
	{
	arc = &Arch;
	cur = getch();
	}


CTextArchReader::~CTextArchReader()
	{
	arc = NULL;
	}


int CTextArchReader::getch()
	{
	char ch;

	if (arc == NULL || arc->Read(&ch, 1) < 1)
		return EOF;
	else if (ch == '\r') 
		return getch();
	else
		return ch;
	}



CTextBufferReader::CTextBufferReader(const char *Buffer, const int OnlySpaces, 
			                         const int SkipComments)
	: CTextReader(OnlySpaces, SkipComments)
	{
	bufp = Buffer;
	cur = getch();
	}


CTextBufferReader::~CTextBufferReader()
	{
	bufp = NULL;
	}


int CTextBufferReader::getch()
	{
	if (bufp == NULL || *bufp == '\0')
		return EOF;
	else if (*bufp == '\r')
		{
		bufp++;
		return getch();
		}
	else
		return *bufp++;
	}

